'use strict';

const db = uniCloud.database()
const $ = db.command.aggregate
const _ = db.command

exports.main = async (event, context) => {
  console.log('收到的参数:', event)

  const { action, params = {} } = event
  console.log('解析后的 action:', action)

  switch (action) {
    case 'generateDescription':
      return await generateDescription(params)

    case 'batchGenerateDescriptions':
      return await batchGenerateDescriptions(params)

    case 'updateConceptHeat':
      return await updateConceptHeat(params)

    case 'getHotConcepts':
      return await getHotConcepts(params)

    case 'searchConcepts':
      return await searchConcepts(params)

    case 'getConceptDetail':
      return await getConceptDetail(params)

    default:
      return {
        code: 404,
        msg: '未找到对应的操作'
      }
  }
}

// 生成概念描述
async function generateDescription({ name }) {
  try {
    if (!name) {
      return {
        code: 400,
        msg: '缺少概念名称'
      }
    }

    // 1. 调用大模型生成描述
    const description = await generateAIDescription(name)

    // 2. 更新数据库
    await db.collection('a_concepts')
      .where({ name })
      .update({
        description,
        update_time: new Date()
      })

    return {
      code: 200,
      msg: 'ok',
      data: { description }
    }

  } catch (e) {
    console.error('生成概念描述异常:', e)
    return {
      code: 500,
      msg: '生成概念描述失败:' + e.message
    }
  }
}

// 调用大模型生成描述
async function generateAIDescription(name) {
  try {
    // 配置信息
    const url = 'https://spark-api-open.xf-yun.com/v1/chat/completions'
    const apiPassword = 'KTmyqFZZVglaDJEmKrvN:RCxEaQXdTtxlwopyUqSC'

    // 构建请求数据
    const data = {
      model: '4.0Ultra',
      messages: [
        {
          role: 'system',
          content: `你是一个专业的股票分析师和技术专家，擅长用简短精炼的语言描述概念的投资价值。
以下是一些优秀的示例：
- 计算机视觉、自然语言处理等细分领域持续发力
- 新能源汽车专利持续增长，带动产业链发展
- 国产替代加速，芯片设计制造专利激增
- 生物医药和医疗器械领域创新活跃
- 云服务和云原生技术专利快速增长
- 5G应用场景不断拓展，带动通信技术创新
- VR/AR等相关技术专利申请活跃
- 工业机器人和服务机器人技术创新加速
描述要求：
1. 突出专利技术创新
2. 强调细分领域发展
3. 体现产业链带动效应
4. 使用专业、具体的表述
5. 必须控制在30字以内
6. 仅描述概念的投资价值，不要描述概念的定义
`

        },
        {
          role: 'user',
          content: `请描述"${name}"这个概念的投资价值，参考上述示例。`
        }
      ],
      temperature: 0.3,  // 降低温度，使输出更稳定
      max_tokens: 64
    }

    // 构建请求头
    const headers = {
      'Authorization': `Bearer ${apiPassword}`,
      'Content-Type': 'application/json'
    }

    // 发送请求
    console.log('发送请求:', {
      url,
      headers,
      data
    })

    const response = await uniCloud.httpclient.request(url, {
      method: 'POST',
      data: data,
      headers: headers,
      dataType: 'json',
      timeout: 30000
    })

    console.log('响应状态码:', response.status)
    console.log('响应数据:', response.data)

    if (response.status === 200 && response.data.code === 0) {
      const result = response.data
      if (result.choices && result.choices.length > 0) {
        return result.choices[0].message.content
      }
    }

    throw new Error('调用大模型失败: ' + JSON.stringify(response.data))

  } catch (e) {
    console.error('调用大模型异常:', e)
    return `${name}是重要的技术创新领域，具有广阔市场前景。`
  }
}

// 更新概念热度
async function updateConceptHeat({ conceptCode }) {
  try {
    if (!conceptCode) {
      return {
        code: 400,
        msg: '缺少概念代码'
      }
    }

    // 1. 获取概念相关的股票代码
    const relations = await db.collection('a_concept_stock_relations')
      .where({ concept_code: conceptCode })
      .get()

    const stockCodes = relations.data.map(item => item.stock_code)

    // 2. 获取相关股票的专利统计
    const patentStats = await db.collection('a_stock_patent_stats')
      .where({
        stock_code: db.command.in(stockCodes)
      })
      .field({
        total_count: true,
        api_call_count: true
      })
      .get()

    // 3. 计算热度
    const heat = calculateHeat({
      stockCount: stockCodes.length,
      patentStats: patentStats.data
    })

    // 4. 更新数据库
    await db.collection('a_concepts')
      .where({ concept_code: conceptCode })
      .update({
        heat,
        update_time: new Date()
      })

    return {
      code: 200,
      msg: 'ok',
      data: { heat }
    }

  } catch (e) {
    console.error('更新概念热度异常:', e)
    return {
      code: 500,
      msg: '更新概念热度失败:' + e.message
    }
  }
}

// 计算热度的辅助函数
function calculateHeat({ stockCount, patentStats }) {
  // 1. 计算专利总量得分 (40%)
  const totalPatents = patentStats.reduce((sum, stat) => sum + (stat.total_count || 0), 0)
  const patentScore = Math.min(totalPatents / 1000, 1) * 40  // 每1000件专利满分

  // 2. 计算访问量得分 (40%)
  const totalVisits = patentStats.reduce((sum, stat) => sum + (stat.api_call_count || 0), 0)
  const visitScore = Math.min(totalVisits / 100, 1) * 40  // 每100次访问满分

  // 3. 计算公司数量得分 (20%)
  const companyScore = Math.min(stockCount / 10, 1) * 20  // 每10家公司满分

  // 4. 计算总分
  const totalScore = patentScore + visitScore + companyScore

  return Math.round(totalScore)
}

// 添加批量处理函数
async function batchGenerateDescriptions({ batchSize = 10, retryTimes = 3 } = {}) {
  try {
    // 1. 获取总记录数
    const countResult = await db.collection('a_concepts')
      .where({
        description: _.or(_.exists(false), _.eq(''))
      })
      .count()
    
    const total = countResult.total
    const pageSize = 100 // uniCloud 单次查询限制
    const pageCount = Math.ceil(total / pageSize)
    
    console.log(`总共找到 ${total} 个需要生成描述的概念，分 ${pageCount} 页处理`)
    
    // 2. 分页获取所有概念
    let allConcepts = []
    for (let page = 0; page < pageCount; page++) {
      const skip = page * pageSize
      const concepts = await db.collection('a_concepts')
        .where({
          description: _.or(_.exists(false), _.eq(''))
        })
        .field({
          name: true,
          concept_code: true
        })
        .skip(skip)
        .limit(pageSize)
        .get()
      
      allConcepts = allConcepts.concat(concepts.data)
      console.log(`已获取第 ${page + 1}/${pageCount} 页概念数据`)
    }

    if (!allConcepts.length) {
      return {
        code: 200,
        msg: '没有需要生成描述的概念'
      }
    }

    console.log(`总共找到 ${allConcepts.length} 个需要生成描述的概念`)

    // 3. 将概念分组进行批处理
    const batches = []
    for (let i = 0; i < allConcepts.length; i += batchSize) {
      batches.push(allConcepts.slice(i, i + batchSize))
    }

    // 4. 批量处理
    let successCount = 0
    let failCount = 0
    
    for (let i = 0; i < batches.length; i++) {
      console.log(`正在处理第 ${i + 1}/${batches.length} 批`)
      
      // 并���一批
      const results = await Promise.allSettled(
        batches[i].map(async concept => {
          for (let retry = 0; retry < retryTimes; retry++) {
            try {
              const description = await generateAIDescription(concept.name)
              await db.collection('a_concepts')
                .where({ concept_code: concept.concept_code })
                .update({
                  description,
                  update_time: new Date()
                })
              successCount++
              return { success: true, name: concept.name }
            } catch (e) {
              if (retry === retryTimes - 1) {
                failCount++
                console.error(`处理概念 ${concept.name} 失败:`, e)
                return { success: false, name: concept.name, error: e.message }
              }
              // 等待一秒后重试
              await new Promise(resolve => setTimeout(resolve, 1000))
            }
          }
        })
      )

      // 每批处理完后等待1秒，避免请求过于频繁
      await new Promise(resolve => setTimeout(resolve, 1000))
    }

    return {
      code: 200,
      msg: '批量生成描述完成',
      data: {
        total: allConcepts.length,
        success: successCount,
        fail: failCount
      }
    }

  } catch (e) {
    console.error('批量生成描述异常:', e)
    return {
      code: 500,
      msg: '批量生成描述失败:' + e.message
    }
  }
}

// 获取热门概念列表
async function getHotConcepts({ limit = 10 } = {}) {
  try {
    console.log('开始获取热门概念, limit:', limit)

    // 1. 获取符合条件的概念
    const concepts = await db.collection('a_concepts')
      .where({
        exchange: 'A'  // 只查询 A 股概念
      })
      .field({
        concept_code: true,
        name: true,
        description: true,
        count: true,     // 使用 count 字段表示公司数量
        update_time: true
      })
      .orderBy('count', 'desc')  // 暂时用 count 代替 heat 进行排序
      .limit(limit)
      .get()

    console.log('获取到热门概念数据:', concepts.data.length, '条')

    // 2. 整合数据
    const result = {
      code: 200,
      msg: 'ok',
      data: {
        list: concepts.data.map(item => ({
          id: item.concept_code,
          name: item.name,
          description: item.description || '',
          heat: item.count || 0,    // 暂时用 count 值代替 heat
          trend: 0,
          companies: item.count || 0,  // 直接使用 count 字段
          updateTime: item.update_time
        }))
      }
    }

    console.log('返回结果:', JSON.stringify(result))
    return result

  } catch (e) {
    console.error('获取热门概念异常:', e)
    return {
      code: 500,
      msg: '获取热门概念失败:' + e.message
    }
  }
}

// 搜索概念
async function searchConcepts({ keyword = '' }) {
  console.log('搜索概念关键词:', keyword)
  
  if (!keyword.trim()) {
    return {
      code: 200,
      msg: 'ok',
      data: { list: [] }
    }
  }

  try {
    // 获取数据库指令引用
    const dbCmd = db.command
    
    const list = await db.collection('a_concepts')
      .where({
        exchange: 'A',  // 条件1：必须是 A 股
        '$or': [{      // 条件2：符合关键词搜索
          name: {
            $regex: keyword,
            $options: 'i'
          }
        }, {
          description: {
            $regex: keyword,
            $options: 'i'
          }
        }]
      })
      .field({
        concept_code: true,
        name: true,
        description: true,
        count: true,     // 使用 count 替代 heat
        update_time: true
      })
      .orderBy('count', 'desc')  // 按公司数量降序排序
      .limit(10)
      .get()
      
    console.log('查询结果:', JSON.stringify(list))

    return {
      code: 200,
      msg: 'ok',
      data: {
        list: list.data.map(item => ({
          id: item.concept_code,
          name: item.name,
          description: item.description || '',
          heat: item.count || 0,    // 暂时用 count 替代 heat
          companies: item.count || 0,  // 直接使用 count 字段
          updateTime: item.update_time
        }))
      }
    }

  } catch (e) {
    console.error('搜索概念异常:', e)
    return {
      code: 500,
      msg: '搜索失败:' + e.message
    }
  }
}

// 获取概念详情
async function getConceptDetail({ id }) {
  try {
    if (!id) {
      return {
        code: 400,
        msg: '缺少概念ID'
      }
    }

    // 1. 获取概念基本信息
    const conceptInfo = await db.collection('a_concepts')
      .where({ concept_code: id })
      .field({
        concept_code: true,
        name: true,
        description: true,
        heat: true,
        update_time: true
      })
      .get()
      .then(res => res.data[0])

    if (!conceptInfo) {
      return {
        code: 404,
        msg: '概念不存在'
      }
    }

    // 2. 获取相关公司列表
    const relations = await db.collection('a_concept_stock_relations')
      .where({ concept_code: id })
      .get()
    
    const stockCodes = relations.data.map(item => item.stock_code)

    // 3. 获取公司信息和专利统计
    const [stockInfos, patentStats] = await Promise.all([
      // 3.1 获取公司基本信息
      db.collection('a_stocks')
        .where({
          stock_code: _.in(stockCodes)
        })
        .field({
          stock_code: true,
          name: true,
          fullname: true,
          industry: true
        })
        .get(),

      // 3.2 获取专利统计信息
      db.collection('a_stock_patent_stats')
        .where({
          stock_code: _.in(stockCodes)
        })
        .field({
          stock_code: true,
          total_count: true,
          sampled_count: true,
          api_call_count: true
        })
        .get()
    ])

    // 4. 构建专利统计映射
    const patentStatsMap = new Map(
      patentStats.data.map(item => [item.stock_code, item])
    )

    // 5. 整合公司信息和专利统计
    const stocks = stockInfos.data.map(stock => {
      const patentStat = patentStatsMap.get(stock.stock_code) || {}
      return {
        code: stock.stock_code,
        name: stock.name,
        fullname: stock.fullname,
        industry: stock.industry,
        patents: {
          total: patentStat.total_count || 0,
          growth: 0  // TODO: 计算增长率
        },
        price: 0,    // TODO: 获取实时价格
        change: 0    // TODO: 获取涨跌幅
      }
    })

    // 6. 计算专利分布TOP5
    const patentData = {
      categories: [],
      series: [{
        name: '专利数量',
        data: []
      }]
    }

    // 按专利数量排序并取前5
    const top5Stocks = [...stocks]
      .sort((a, b) => b.patents.total - a.patents.total)
      .slice(0, 5)

    patentData.categories = top5Stocks.map(stock => stock.name)
    patentData.series[0].data = top5Stocks.map(stock => stock.patents.total)

    // 7. 返回结果
    return {
      code: 200,
      msg: 'ok',
      data: {
        // 基本信息
        name: conceptInfo.name,
        description: conceptInfo.description,
        totalCompanies: stocks.length,
        totalPatents: stocks.reduce((sum, stock) => sum + stock.patents.total, 0),
        trend: 0,  // TODO: 计算趋势

        // 专利分布数据
        patentData,

        // 相关股票列表
        stocks: stocks.sort((a, b) => b.patents.total - a.patents.total)  // 按专利数量降序
      }
    }

  } catch (e) {
    console.error('获取概念详情异常:', e)
    return {
      code: 500,
      msg: '获取概念详情失败:' + e.message
    }
  }
} 